题目描述:
给你一个长度为 n
的整数数组 nums
,其中 n > 1,返回输出数组 output
,其中 output[i]
等于 nums
中除 nums[i]
之外其余各元素的乘积。
进阶:你可以在常数空间复杂度内完成这个题目吗?(出于对空间复杂度分析的目的,输出数组不被视为额外空间。)
示例:
1 | 输入: [1,2,3,4] |
提示:题目数据保证数组之中任意元素的全部前缀元素和后缀(甚至是整个数组)的乘积都在 32 位整数范围内。
说明: 请不要使用除法,且在 O(n) 时间复杂度内完成此题。
链接:
https://leetcode-cn.com/problems/product-of-array-except-self
题目分析
题目中要求我们不使用除法,而实际上使用除法也存在的一定的问题:如果数组中含 0,除以 0 也会出现问题。我们要求的是除了本身以外其余各元素的乘积,而且要达到 $O(n)$ 的时间复杂度,也即前面的乘积结果最好能使用上,怎么使用呢?其实我们要求的结果,可以看做是左边部分的乘积乘上右边部分的乘积。那么先不考虑空间复杂度的问题,我们可以使用两个数组,一个记录从左到右分别乘起来的乘积,一个记录从右到左分别乘起来的乘积,则 result[i] = left[i-1] * right[i+1]
。按照这个思路,我们只需要从左到右和从右到左分别遍历一次,得到这两个数组,最后再遍历一次求出各个位置的结果就可以。
接下来考虑,该如何减小空间复杂度呢?答案数组是不计入所需空间的,我们从左到右的遍历,可以直接记入答案数组中,当然,需要一点小小的变化,第一个数直接记入到第二个空位中,因为第二个结果才需要第一个数的乘积。然后进行从右到左的遍历中,我们只需要使用一个数记录最后的乘积值,作为转移的依据,而乘积结果则可以直接乘入到答案数组中,这样还省去了第三次遍历的过程。
1 | class Solution { |
时间复杂度:$O(n)$,其中 $n$ 是数组的大小。我们对数组进行了两次遍历。
空间复杂度:$O(1)$。答案数组不计入空间复杂度中,而我们只需要额外的常数个变量。